﻿using System;
using System.Collections.Generic;

namespace BizElements.Generator
{
    public sealed class Triple<TKey1, TKey2, TValue>
        where TKey1 : IConvertible
        where TKey2 : IConvertible
        where TValue : IConvertible
    {
        public Triple()
        {
        }

        public Triple(TKey1 key1, TKey2 key2, TValue value)
        {
            this.Key1 = key1;
            this.Key2 = key2;
            this.Value = value;
        }

        public TKey1 Key1 { get; set; }
        public TKey2 Key2 { get; set; }
        public TValue Value { get; set; }

        public static IDictionary<TKey1, IDictionary<TKey2, TValue>> ParseDictionary(string delimitedTriples, char tripleDelimiter, char subkeyDelimiter, char valueDelimiter)
        {
            var parsedTriples = new Dictionary<TKey1, IDictionary<TKey2, TValue>>();
            if (string.IsNullOrEmpty(delimitedTriples))
                return parsedTriples;

            string[] tripletStrings = delimitedTriples.Split(tripleDelimiter);
            foreach (string keySubkeyAndValue in tripletStrings)
            {
                Triple<TKey1, TKey2, TValue> triple = Parse(keySubkeyAndValue, subkeyDelimiter, valueDelimiter);
                if (triple != null)
                {
                    if (!parsedTriples.ContainsKey(triple.Key1))
                        parsedTriples[triple.Key1] = new Dictionary<TKey2, TValue>();

                    parsedTriples[triple.Key1][triple.Key2] = triple.Value;
                }
            }

            return parsedTriples;
        }

        public static Triple<TKey1, TKey2, TValue> Parse(string keySubkeyAndValue, char subkeyDelimiter, char valueDelimiter)
        {
            if (string.IsNullOrEmpty(keySubkeyAndValue))
                return null;

            int dotIndex = keySubkeyAndValue.IndexOf(subkeyDelimiter);
            if (dotIndex < 0)
                return null;
            int equalsIndex = keySubkeyAndValue.IndexOf(valueDelimiter);
            if (equalsIndex < 0)
                return null;
            if (equalsIndex < dotIndex)
                return null;

            Triple<TKey1, TKey2, TValue> result = new Triple<TKey1, TKey2, TValue>();
            
            string key1 = keySubkeyAndValue.Substring(0, dotIndex).Trim();
            if (string.IsNullOrEmpty(key1))
                return null;
            result.Key1 = (TKey1)Convert.ChangeType(key1, typeof(TKey1));            

            int variableIndex = dotIndex + 1;
            int variableLen = equalsIndex - variableIndex;
            string subkey = keySubkeyAndValue.Substring(variableIndex, variableLen).Trim();
            if (string.IsNullOrEmpty(subkey))
                return null;
            result.Key2 = (TKey2)Convert.ChangeType(subkey, typeof(TKey2));

            if (equalsIndex < keySubkeyAndValue.Length - 1)
            {
                string value = keySubkeyAndValue.Substring(equalsIndex + 1).Trim();
                result.Value = (TValue)Convert.ChangeType(value, typeof(TValue));
            }
            else
            {
                result.Value = default(TValue);
            }

            return result;
        }
    }
}
